/**
 * Created by qunxing.du on 2016/7/21.
 * Copyright 2016 汉威.智慧环保事业部 Limited.
 * All rights reserved.
 */
package com.hw.one.collect.zzcity.analysis;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

import com.hw.one.collect.client.HttpClient;
import com.hw.one.collect.dust.po.SiteInfo;
import com.hw.one.collect.dust.redis.BaseRedis;
import com.hw.one.collect.mapper.SiteDao;
import com.hw.one.collect.po.SiteAirConcentrationPO;
import com.hw.one.collect.util.OneAuthUtil;
import com.hw.one.collect.zzcity.constants.ZzCityConstants;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

import com.hw.one.collect.util.ConvertUtil;

import javax.annotation.Resource;

/**
 * 原始小时数据AQI计算分析
 */
@Component
public class HourAQIAnalysis {
	private static Logger log = Logger.getLogger(HourAQIAnalysis.class);
	private static final int MAX_LIMIT = 2;

	@Resource
	private SiteDao siteDao;
	@Resource
	private BaseRedis baseRedis;
	/**
	 * 获取站点信息
	 */
	private String getSiteName(String siteCode) {
		String siteName = "";
		String[] ucodes = ZzCityConstants.UCODE.split(",");
		List<String> siteCodeList = Arrays.asList(ucodes);
		Map<String, Object> map = new HashMap<>();
		map.put("siteCodeList", siteCodeList);
		List<SiteInfo> siteInfoList = siteDao.selectSiteInfoBySiteCodeList(map);
		for (SiteInfo siteInfo : siteInfoList) {
			if (siteCode.equals(siteInfo.getSiteCode())) {
				siteName = siteInfo.getSiteName();
			}
			baseRedis.insert("zzCity" + siteInfo.getSiteCode(), siteInfo.getSiteName());
			baseRedis.insert("siteTypeCode" + siteInfo.getSiteCode(), siteInfo.getSiteTypeCode());
		}
		return siteName;

	}
	public synchronized List<Map> analysisHourAQI(Object data) throws Exception {
		List<SiteAirConcentrationPO> siteAirQualityPOList = new ArrayList<>();
 		List<Map> analysisList = (List<Map>) data;
		// 计算AQI相关信息
		for (Map map : analysisList) {
			Integer PM25 = ConvertUtil.toInteger(map.get("PM25"));
			Integer PM10 = ConvertUtil.toInteger(map.get("PM10"));
			Integer O3 = ConvertUtil.toInteger(map.get("O3"));
			Integer SO2 = ConvertUtil.toInteger(map.get("SO2"));
			Integer NO2 = ConvertUtil.toInteger(map.get("NO2"));
			Float CO = ConvertUtil.toFloat(map.get("CO"));
			// IAQI
			Integer SO2IAQI = cal_SO2_iaqi(SO2);
			Integer NO2IAQI = cal_NO2_iaqi(NO2);
			Integer PM10IAQI = cal_pm10_iaqi(PM10);
			Integer COIAQI = cal_CO_iaqi(CO);
			Integer O3IAQI = cal_O3_iaqi(O3);
			Integer PM25IAQI = cal_pm25_iaqi(PM25);
			Integer AQI = getAQI(SO2IAQI, NO2IAQI, PM10IAQI, COIAQI, O3IAQI, PM25IAQI);// AQI
			Integer AQILevel = null;// AQI级别
			String pollutant = null;// 首要污染物
			if (AQI != null) {
				AQILevel = getAQILevel(AQI);// AQI级别
				pollutant = getPollutant(AQI, SO2IAQI, NO2IAQI, PM10IAQI, COIAQI, O3IAQI, PM25IAQI);
			}
			map.put("AQI", AQI);// AQI
			map.put("pollutant", pollutant);// 首要污染物
			map.put("AQILevel", AQILevel);// AQI级别
			map.put("PM25IAQI", PM25IAQI);
			map.put("PM10IAQI", PM10IAQI);
			map.put("COIAQI", COIAQI);
			map.put("SO2IAQI", SO2IAQI);
			map.put("NO2IAQI", NO2IAQI);
			map.put("O3IAQI", O3IAQI);
			log.info("recTime:" + map.get("recTime") + "，UCode：" + map.get("UCode") + "，AQI：" + AQI + ",pollutant:"
					+ pollutant + ",AQILevel:" + AQILevel + ",PM25IAQI：" + PM25IAQI + ",PM10IAQI：" + PM10IAQI
					+ ",COIAQI：" + COIAQI + ",SO2IAQI：" + SO2IAQI + ",NO2IAQI：" + NO2IAQI + ",O3IAQI：" + O3IAQI);
		}
		return analysisList;
	}


	public synchronized List<SiteAirConcentrationPO> analysisHourData(Object data) throws Exception {
		List<SiteAirConcentrationPO> siteAirQualityPOList = new ArrayList<>();
 		List<Map> analysisList = (List<Map>) data;
		String createTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
		// 计算AQI相关信息
		for (Map map : analysisList) {
			Integer PM25 = ConvertUtil.toInteger(map.get("PM25"));
			Integer PM10 = ConvertUtil.toInteger(map.get("PM10"));
			Integer O3 = ConvertUtil.toInteger(map.get("O3"));
			Integer SO2 = ConvertUtil.toInteger(map.get("SO2"));
			Integer NO2 = ConvertUtil.toInteger(map.get("NO2"));
			Float CO = ConvertUtil.toFloat(map.get("CO"));
			Float TEMP = ConvertUtil.toFloat(map.get("TEMP"));
			Float HUM = ConvertUtil.toFloat(map.get("HUM"));
			Float WD = ConvertUtil.toFloat(map.get("WD"));
			Float WS = ConvertUtil.toFloat(map.get("WS"));

			SiteAirConcentrationPO siteAir = new SiteAirConcentrationPO();
			siteAir.setPM10(PM10 == null || PM10 <= 0? "0" : String.valueOf(PM10));
			siteAir.setPM25(PM25 == null || PM25 <= 0 ? "0" : String.valueOf(PM25));
			siteAir.setSO2(SO2 == null || SO2 <= 0 ? "0" : String.valueOf(SO2));
			siteAir.setNO2(NO2 == null || NO2 <= 0 ? "0" : String.valueOf(NO2));
			siteAir.setCO(CO == null || CO <= 0 ? "0" : String.valueOf(CO));
			siteAir.setO3(O3 == null || O3 <= 0 ? "0" : String.valueOf(O3));
			siteAir.setTEMP(TEMP == null || TEMP <= 0 ? null : String.valueOf(TEMP));
			siteAir.setHUM(HUM == null || HUM <= 0 ? null : String.valueOf(HUM));
			siteAir.setWD(WD == null || WD <= 0 ? null : String.valueOf(WD));
			siteAir.setWS(WS == null || WS <= 0 ? null : String.valueOf(WS));

			siteAir.setMONITORTIME((String) map.get("recTime"));
			siteAir.setDATASOURCES("webapi_zzs");
			siteAir.setCREATETIME(createTime);
			siteAir.setSITECODE(String.valueOf(map.get("UCode")));
			String siteName = baseRedis.get("zzCity"+siteAir.getSITECODE());
			String siteTypeCode = baseRedis.get("siteTypeCode" + siteAir.getSITECODE());
			if (null == siteName || "".equals(siteName)) {
				siteName = getSiteName(siteAir.getSITECODE());
			}
			if (null !=siteName && !"".equals(siteName)) {
				siteAir.setSITENAME(siteName);
				siteAir.setSITETYPECODE(siteTypeCode);
			}
			siteAirQualityPOList.add(siteAir);
		}
		return siteAirQualityPOList;
	}







	/**
	 * 计算首要污染物
	 * 
	 * @param AQI
	 * @param SO2IAQI
	 * @param NO2IAQI
	 * @param PM10IAQI
	 * @param COIAQI
	 * @param O3IAQI
	 * @param PM25IAQI
	 * @return
	 */
	private String getPollutant(Integer AQI, Integer SO2IAQI, Integer NO2IAQI, Integer PM10IAQI, Integer COIAQI,
			Integer O3IAQI, Integer PM25IAQI) {
		if (AQI <= 50) {
			return null;
		}
		Map<String, Integer> pollutants = new HashMap<>();
		pollutants.put("SO2", SO2IAQI);
		pollutants.put("NO2", NO2IAQI);
		pollutants.put("PM10", PM10IAQI);
		pollutants.put("CO", COIAQI);
		pollutants.put("O3", O3IAQI);
		pollutants.put("PM25", PM25IAQI);
		Iterator<String> its = pollutants.keySet().iterator();
		StringBuffer pollutantSb = new StringBuffer();// 首要污染物
		while (its.hasNext()) {
			String key = its.next();
			Integer IAQI = pollutants.get(key);
			if (IAQI == null) {
				continue;
			}
			if (IAQI.intValue() == AQI.intValue()) {
				pollutantSb.append(key).append(",");
			}
		}

		// 删除最后多余的分隔符
		if (pollutantSb.length() > 0) {
			pollutantSb.deleteCharAt(pollutantSb.length() - 1);
		}
		return pollutantSb.toString();
	}

	/**
	 * 计算pm25的分指数
	 * 
	 * @param cp
	 * @return
	 * @author fbl
	 * @create_time 2015年8月13日下午7:18:01
	 */
	public Integer cal_pm25_iaqi(Integer cp) {
		if (cp == null) {
			return null;
		}
		int iaqi[] = { 0, 50, 100, 150, 200, 300, 400, 500 };
		int pm25[] = { 0, 35, 75, 115, 150, 250, 350, 500 };
		int BPH = 0, BPL = 0, IAQIH = 0, IAQIL = 0;
		if (cp < 0)
			cp = 0;
		if (cp > 500)
			return 500;

		int i;
		for (i = 1; i < pm25.length; i++) {
			if (cp >= pm25[i - 1] && cp < pm25[i]) {
				break;
			}
		}

		if (i == pm25.length)
			i = pm25.length - 1;
		BPH = pm25[i];
		BPL = pm25[i - 1];
		IAQIH = iaqi[i];
		IAQIL = iaqi[i - 1];

		return iaqi(BPH, BPL, IAQIH, IAQIL, cp);
	}

	/**
	 * 计算pm10的分指数
	 * 
	 * @param cp
	 * @return
	 * @author fbl
	 * @create_time 2015年8月13日下午7:29:03
	 */
	public Integer cal_pm10_iaqi(Integer cp) {
		if (cp == null) {
			return null;
		}
		int iaqi[] = { 0, 50, 100, 150, 200, 300, 400, 500 };
		int pm10[] = { 0, 50, 150, 250, 350, 420, 500, 600 };
		int BPH = 0, BPL = 0, IAQIH = 0, IAQIL = 0;
		if (cp < 0)
			cp = 0;
		if (cp > 600)
			return 500;

		int i;
		for (i = 1; i < pm10.length; i++) {
			if (cp >= pm10[i - 1] && cp < pm10[i]) {
				break;
			}
		}

		if (i == pm10.length)
			i = pm10.length - 1;
		BPH = pm10[i];
		BPL = pm10[i - 1];
		IAQIH = iaqi[i];
		IAQIL = iaqi[i - 1];

		return iaqi(BPH, BPL, IAQIH, IAQIL, cp);
	}

	/**
	 * 计算SO2的分指数
	 * 
	 * @param cp
	 * @return
	 * @author fbl
	 * @create_time 2015年8月13日下午7:29:03
	 */
	public Integer cal_SO2_iaqi(Integer cp) {
		if (cp == null) {
			return null;
		}
		int iaqi[] = { 0, 50, 100, 150, 200 };
		int so2[] = { 0, 150, 500, 650, 800 };
		int BPH = 0, BPL = 0, IAQIH = 0, IAQIL = 0;
		if (cp < 0)
			cp = 0;
		if (cp > 800)
			return 200;

		int i;
		for (i = 1; i < so2.length; i++) {
			if (cp >= so2[i - 1] && cp < so2[i]) {
				break;
			}
		}

		if (i == so2.length)
			i = so2.length - 1;
		BPH = so2[i];
		BPL = so2[i - 1];
		IAQIH = iaqi[i];
		IAQIL = iaqi[i - 1];

		return iaqi(BPH, BPL, IAQIH, IAQIL, cp);
	}

	/**
	 * 计算NO2的分指数
	 * 
	 * @param cp
	 * @return
	 * @author fbl
	 * @create_time 2015年8月13日下午7:29:03
	 */
	public Integer cal_NO2_iaqi(Integer cp) {
		if (cp == null) {
			return null;
		}
		int iaqi[] = { 0, 50, 100, 150, 200, 300, 400, 500 };
		int no2[] = { 0, 100, 200, 700, 1200, 2340, 3090, 3840 };
		int BPH = 0, BPL = 0, IAQIH = 0, IAQIL = 0;
		if (cp < 0)
			cp = 0;
		if (cp > 3840)
			return 500;

		int i;
		for (i = 1; i < no2.length; i++) {
			if (cp >= no2[i - 1] && cp < no2[i]) {
				break;
			}
		}

		if (i == no2.length)
			i = no2.length - 1;
		BPH = no2[i];
		BPL = no2[i - 1];
		IAQIH = iaqi[i];
		IAQIL = iaqi[i - 1];

		return iaqi(BPH, BPL, IAQIH, IAQIL, cp);
	}

	/**
	 * 计算CO的分指数
	 * 
	 * @param v
	 * @return
	 * @author fbl
	 * @create_time 2015年8月13日下午7:29:03
	 */
	public Integer cal_CO_iaqi(Float v) {
		if(v == null)
			return null;
		float s = v;
		int cp = 0;
		if (s - (int) s > 0.5D)
			cp = (int) s + 1;
		else
			cp = (int) s;

		int iaqi[] = { 0, 50, 100, 150, 200, 300, 400, 500 };
		int co[] = { 0, 5, 10, 35, 60, 90, 120, 150 };
		int BPH = 0, BPL = 0, IAQIH = 0, IAQIL = 0;
		if (cp < 0)
			cp = 0;
		if (cp > 150)
			return 500;

		int i;
		for (i = 1; i < co.length; i++) {
			if (cp >= co[i - 1] && cp < co[i]) {
				break;
			}
		}

		if (i == co.length)
			i = co.length - 1;
		BPH = co[i];
		BPL = co[i - 1];
		IAQIH = iaqi[i];
		IAQIL = iaqi[i - 1];

		return iaqi(BPH, BPL, IAQIH, IAQIL, cp);
	}

	/**
	 * 计算O3的分指数
	 * 
	 * @param cp
	 * @return
	 * @author fbl
	 * @create_time 2015年8月13日下午7:29:03
	 */
	public Integer cal_O3_iaqi(Integer cp) {
		if (cp == null) {
			return null;
		}
		int iaqi[] = { 0, 50, 100, 150, 200, 300, 400, 500 };
		int o3[] = { 0, 160, 200, 300, 400, 800, 1000, 1200 };
		int BPH = 0, BPL = 0, IAQIH = 0, IAQIL = 0;
		if (cp < 0)
			cp = 0;
		if (cp > 1200)
			return 500;

		int i;
		for (i = 1; i < o3.length; i++) {
			if (cp >= o3[i - 1] && cp < o3[i]) {
				break;
			}
		}

		if (i == o3.length)
			i = o3.length - 1;
		BPH = o3[i];
		BPL = o3[i - 1];
		IAQIH = iaqi[i];
		IAQIL = iaqi[i - 1];

		return iaqi(BPH, BPL, IAQIH, IAQIL, cp);
	}

	/**
	 * 分指数计算公式
	 * 
	 * @param BPH
	 * @param BPL
	 * @param IAQIH
	 * @param IAQIL
	 * @param cp
	 * @return
	 * @author fbl
	 * @create_time 2015年8月13日下午7:23:27
	 */
	public static int iaqi(int BPH, int BPL, int IAQIH, int IAQIL, int cp) {
		return ((IAQIH - IAQIL) * (cp - BPL) / (BPH - BPL) + IAQIL);
	}


	/**
	 * 计算AQI
	 *
	 * @param SO2IAQI
	 * @param NO2IAQI
	 * @param PM10IAQI
	 * @param COIAQI
	 * @param O3IAQI
	 * @param PM25IAQI
	 * @return
	 */
	private Integer getAQI(Integer SO2IAQI, Integer NO2IAQI, Integer PM10IAQI, Integer COIAQI, Integer O3IAQI,
			Integer PM25IAQI) {
		Integer[] IAQIObjs = new Integer[] { SO2IAQI, NO2IAQI, PM10IAQI, COIAQI, O3IAQI, PM25IAQI };
		if (isGte3Null(IAQIObjs)) {
			return null;
		}
		int[] IAQIs = filterNull(IAQIObjs);
		return getAQI(IAQIs);
	}

	/**
	 * 计算最大值
	 * 
	 * @param args
	 * @return
	 */
	private Integer getAQI(int[] args) {
		return NumberUtils.max(args);
	}

	/**
	 * 是否有3个null值
	 * 
	 * @param args
	 * @return
	 */
	private boolean isGte3Null(Integer[] args) {
		int count = 0;
		for (Integer o : args) {
			if (o == null) {
				count++;
			}
		}
		return count >= MAX_LIMIT ? true : false;
	}

	/**
	 * 过虑NULL
	 * 
	 * @param args
	 * @return
	 */
	private int[] filterNull(Integer[] args) {
		int[] result = new int[args.length];
		int j = 0;
		for (int i = 0; i < args.length; i++) {
			if (args[i] != null) {
				result[j++] = args[i];
			}
		}
		return result;
	}

	/**
	 * 是否有3个大于0的值
	 * 
	 * @param args
	 * @return
	 */
	@Deprecated
	private boolean isGte3Zero(int[] args) {
		int count = 0;
		for (int i : args) {
			if (i == 0) {
				count++;
			}
		}
		return count >= MAX_LIMIT ? true : false;
	}

	/**
	 * 计算AQI 级别
	 *
	 * @param AQI
	 * @return
	 */
	private Integer getAQILevel(int AQI) {
		Integer level = null;
		if (AQI >= 0 && AQI <= 50) {
			level = 1;
		} else if (AQI >= 51 && AQI <= 100) {
			level = 2;
		} else if (AQI >= 101 && AQI <= 150) {
			level = 3;
		} else if (AQI >= 151 && AQI <= 200) {
			level = 4;
		} else if (AQI >= 201 && AQI <= 300) {
			level = 5;
		} else {
			level = 6;
		}
		return level;
	}
}
